/*
 * @brief:
 *      三角电磁铁对象
 *
 * ChangeLog        Author          Notes
 * 2015.09.09       Herbert         First Version
 */
#include "mhdef.h"
#include "crgcam.h"
#include "em_cam.h"
#include "ccycle.h"
#include <assert.h>
#include <malloc.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>

#define CAM_CYCLE_TIME  100

CAM* cam_new()
{
    int i = 0;

    CAM *cam = (CAM*)malloc(sizeof (CAM));

    ccycle_init(&cam->cycle);
    ccycle_init(&cam->reset_cycle);

    timer_init(&cam->timer);

    for (i = 0; i < 8; i++)
    {
        cam->state[i] = 0xFF;
        cam->state_bk[i] = 0xFF;
    }

    cam->exec = emcam_exec;
    cam->exec_reset_state = NULL;
#if (MH_SYS_CAM == 1 && MH_JTCS_CAM == 1)
    cam->exec_reset_state = emcam_exec_reset_state;
#endif
    return cam;
}

void cam_set_cycle(CAM *cam, CCYCLE *cycle, CCYCLE *reset_cycle)
{
    assert(cam != NULL);
    assert(cycle != NULL);
    assert(reset_cycle != NULL);

    memcpy(&cam->cycle, cycle, sizeof (CCYCLE));
    memcpy(&cam->reset_cycle, reset_cycle, sizeof (CCYCLE));
}

/*
 * @param cam: 三角电磁铁对象
 * @param type: 动作类型，动作或者复位
 * @param group: 组序号，从左机头到右机头从左往右依次为0-7
 * @param num: 组内序号0-5一次为左接针，吊目，右接针，左二度，翻针，右二度
 */
int cam_exec(MH_UDP *pudp, CAM *cam, ActType type, int group, int num)
{
    assert(cam != NULL);
    assert((group >= 0) && (group < 8));

    uchar state[8] = { 0 };
    if (type == RESET)
    {
        uchar state_tmp[8] = { 0 };

        cam->state[group] |= 0x01 << num;
        state_tmp[group] = 0x01 << num;

        cam_convert_state(cam, &state_tmp[0], &state[0], UP2DOWN, TRUE);
        cam_convert_state(cam, &state_tmp[4], &state[4], UP2DOWN, TRUE);

        printf("state[0] = %x, state[1] = %x, state[2] = %x\n",
            state[0], state[1], state[2]);
    }
    else
    {
        cam->state[group] ^= 0x01 << num;

        cam_convert_state(cam, &cam->state[0], &state[0], UP2DOWN, FALSE);
        cam_convert_state(cam, &cam->state[4], &state[4], UP2DOWN, FALSE);
    }

    return cam->exec(pudp, type, state);
}

int cam_exec_group(MH_UDP *pudp, CAM *cam, int group)
{
    assert(cam != NULL);
    assert((group >= 0) && (group < 8));

    ActType type = ACT;
    int i = 0, ret = -1;
    uchar state[8] = { 0 };
    uchar group_state = cam_get_group_state(cam, group);
    if (group_state == UP)
    {
        for(i = 0; i < 8; i++)
        {
            cam->state[group] |= 0X01 << i;
            cam_convert_state(cam, cam->state, state, UP2DOWN, FALSE);
            ret = cam->exec(pudp, type, state);
            usleep(100000);
        }
    }
    else
    {
         for(i = 0; i < 8; i++)
        {
            cam->state[group] &= 0XFE << i;
            cam_convert_state(cam, cam->state, state, UP2DOWN, FALSE);
            ret = cam->exec(pudp, type, state);
            usleep(100000);
        }
    }

    return ret;
}
/*
 * @note: 将三角状态置到复位状态
 */
int cam_exec_reset_state(CAM *cam)
{
    assert(cam != NULL);
    int ret = 0;

    /* 直选单系统 */
    uchar cur_state[2] = { 0xFF, 0xFF };
    uchar reset_state[2] = { 0xFF, 0xFF };
    cam_convert_state(cam, reset_state, reset_state, UP2DOWN, FALSE);

    printf("cur_state[0] = %x, cur_state[1] = %x\n", cur_state[0], cur_state[1]);
    printf("reset_state[0] = %x, reset_state[1] = %x\n", reset_state[0], reset_state[1]);

    ret = cam->exec_reset_state(cur_state, reset_state, 2);

    return ret;
}

/*
 * @param user_data: 纱嘴对象
 */
int cam_exec_cycle(MH_UDP *pudp, void *user_data)
{
    assert(user_data != NULL);

    CAM *cam = (CAM*)user_data;
    int group = -1;
    int index = -1;
    CCYCLE *cycle = NULL;
    ActType type = RESET;

    if (ccycle_get_state(&cam->reset_cycle) != CYCLE_STOP)
    {
        type = RESET;
        cycle = &cam->reset_cycle;
    }
    else if (ccycle_get_state(&cam->cycle) != CYCLE_STOP)
    {
        type = ACT;
        cycle = &cam->cycle;
    }

    if (cycle == NULL)
    {
        return 0;
    }

    group = cycle->group;
    index = cycle->index;

    if (ccycle_get_state(cycle) == CYCLE_READY)
    {
        ccycle_set_state(cycle, CYCLE_EXEC);
    }
    else
    {
        FEEDBACK fb;
        int ret = 0;
        memset(&fb, 0, sizeof (FEEDBACK));

        ret = feedback_get_error_state(pudp, &fb, (group > 3));
        if (ret < 0)
        {
            return ret;
        }

        ret = cam_encount_error(cam, &fb, cycle);

        if (ret < 0)
        {
            printf("encount error\n");
            return ret;
        }

        ccycle_exec(cycle);

        if (type == RESET)
        {
            if (ccycle_complete(cycle))
            {
                ccycle_stop(cycle);
                if (cam->exec_reset_state != NULL)
                {
                    int ret = 0;
                    ret = cam_exec_reset_state(cam);
                    if (ret < 0)
                    {
                        return ret;
                    }
                }
                if (ccycle_get_state(&cam->cycle) != CYCLE_STOP)
                {
                    /* 执行动作循环 */
                    timer_start(&cam->timer, 0, CAM_CYCLE_TIME, cam_exec_cycle);
                }
                return 0;
            }
        }

        group = ccycle_get_group(cycle);
        index = ccycle_get_index(cycle);

    }

    if (group < 0 || index < 0)
    {
        return -1;
    }
    timer_start(&cam->timer, 0, CAM_CYCLE_TIME, cam_exec_cycle);

    return cam_exec(pudp, cam, type, group, index);
}

int cam_get_next_diff(CAM *cam, CCYCLE *cycle, int *group, int *index)
{
    assert(cam != NULL);
    assert(cycle != NULL);
    assert(group != NULL);
    assert(index != NULL);

    do
    {
        int filter = 0;
        ccycle_exec(cycle);

        if (ccycle_complete(cycle))
        {
            return FALSE;
        }

        *group = ccycle_get_group(cycle);
        *index = ccycle_get_index(cycle);

        filter = 0x01 << *index;
        if (((cam->state[*group] ^ cam->state_bk[*group]) & filter) == 0)
        {
            /* 状态相同 */
            continue;
        }

        break;
    } while (1);

    return TRUE;
}

int cam_restore(MH_UDP *pudp, void *user_data)
{
    assert(user_data != NULL);

    CAM *cam = (CAM*)user_data;
    int group = -1;
    int index = -1;
    CCYCLE *cycle = NULL;

    cycle = &cam->reset_cycle;

    if (ccycle_get_state(cycle) == CYCLE_STOP)
    {
        return 0;
    }


    if (ccycle_get_state(cycle) == CYCLE_READY)
    {
        int filter = 0;
        ccycle_set_state(cycle, CYCLE_EXEC);
        group = cycle->group;
        index = cycle->index;

        filter = 0x01 << index;

        if (((cam->state[group] ^ cam->state_bk[group]) & filter) == 0)
        {
            if (!cam_get_next_diff(cam, cycle, &group, &index))
            {
                ccycle_stop(cycle);
                return 0;
            }
        }
    }
    else
    {
        FEEDBACK fb;

        int ret = feedback_get_error_state(pudp, &fb, (group > 1));

        if (ret < 0)
        {
            return ret;
        }

        ret = cam_encount_error(cam, &fb, cycle);

        if (ret < 0)
        {
            printf("encount error\n");
            return ret;
        }

        if (!cam_get_next_diff(cam, cycle, &group, &index))
        {
            ccycle_stop(cycle);
            return 0;
        }
    }

    if (group < 0 || index < 0)
    {
        return -1;
    }

    timer_start(&cam->timer, 0, CAM_CYCLE_TIME, cam_restore);

    return cam_exec(pudp, cam, ACT, group, index);
}

/*
 * @note: 用于检测单个测试的错误
 */
int cam_check_error(MH_UDP *pudp, void *user_data)
{
    assert(user_data != NULL);
    CAM *cam = (CAM*)user_data;
    FEEDBACK fb;
    int ret = 0;
    int group = ccycle_get_group(&cam->cycle);

    memset(&fb, 0, sizeof (FEEDBACK));

    ret = feedback_get_error_state(pudp, &fb, (group > 3));
    if (ret < 0)
    {
        return ret;
    }

    ret = cam_encount_error(cam, &fb, NULL);

    if (ret < 0)
    {
        return ret;
    }

    return 0;
}

int cam_exec_timer(MH_UDP *pudp, CAM *cam)
{
    assert(cam != NULL);
    return timer_exec(pudp, &cam->timer, (void*)cam);
}

/*
 * @param cam: 三角对象，unused
 * @param cam_state_in: 要转换的三角状态
 * @param cam_state_out: 转换之后的三角状态
 * @param dir: 转换方向
 * @param reset: 是否复位
 * @note: 转换三角状态
 */
#if (MH_SYS_CAM > 1)
void cam_convert_state(CAM *cam_unsed, uchar *cam_state_in, uchar *cam_state_out,
    int dir, BOOL reset_cmd)
{
    assert(cam_state_in != NULL);
    assert(cam_state_out != NULL);

    CAM_DOWN_FMT df = { { 0 } };
    CAM_DOWN_FMT reset;
    CAM_FMT cam[4] = { { 0 } };

    reset.cam1.all = 0x9D;
    reset.cam2.all = 0x9D;
    reset.cam3.all = 0xBB;

    if (reset_cmd)
    {
        reset.cam1.all = 0xFF;
        reset.cam2.all = 0xFF;
        reset.cam3.all = 0xFF;
    }

    if (dir == DOWN2UP)
    {
        /* 下位机格式转换为上位机格式 */
        memcpy(&df, cam_state_in, 3);

        /* 左系统前板 */
        cam[0].bits.zjz = (df.cam3.bits.qzjz_l == reset.cam3.bits.qzjz_l);
        cam[0].bits.dm = (df.cam3.bits.qdm_l == reset.cam3.bits.qdm_l);
        cam[0].bits.yjz = (df.cam3.bits.qyjz_l == reset.cam3.bits.qyjz_l);
        cam[0].bits.yed = (df.cam3.bits.qyed_l == reset.cam3.bits.qyed_l);
        cam[0].bits.zed = (df.cam1.bits.qzed_l == reset.cam1.bits.qzed_l);
        cam[0].bits.fz = (df.cam1.bits.qfz_l == reset.cam1.bits.qfz_l);
        /* 左系统后板 */
        cam[1].bits.zjz = (df.cam1.bits.hzjz_l == reset.cam1.bits.hzjz_l);
        cam[1].bits.dm = (df.cam1.bits.hdm_l == reset.cam1.bits.hdm_l);
        cam[1].bits.yjz = (df.cam1.bits.hyjz_l == reset.cam1.bits.hyjz_l);
        cam[1].bits.yed = (df.cam1.bits.hyed_l == reset.cam1.bits.hyed_l);
        cam[1].bits.zed = (df.cam1.bits.hzed_l == reset.cam1.bits.hzed_l);
        cam[1].bits.fz = (df.cam1.bits.hfz_l == reset.cam1.bits.hfz_l);
        /* 右系统前板 */
        cam[2].bits.zjz = (df.cam3.bits.qzjz_r == reset.cam3.bits.qzjz_r);
        cam[2].bits.dm = (df.cam3.bits.qdm_r == reset.cam3.bits.qdm_r);
        cam[2].bits.yjz = (df.cam3.bits.qyjz_r == reset.cam3.bits.qyjz_r);
        cam[2].bits.yed = (df.cam3.bits.qyed_r == reset.cam3.bits.qyed_r);
        cam[2].bits.zed = (df.cam2.bits.qzed_r == reset.cam2.bits.qzed_r);
        cam[2].bits.fz = (df.cam2.bits.qfz_r == reset.cam2.bits.qfz_r);
        /* 右系统后板 */
        cam[3].bits.zjz = (df.cam2.bits.hzjz_r == reset.cam2.bits.hzjz_r);
        cam[3].bits.dm = (df.cam2.bits.hdm_r == reset.cam2.bits.hdm_r);
        cam[3].bits.yjz = (df.cam2.bits.hyjz_r == reset.cam2.bits.hyjz_r);
        cam[3].bits.yed = (df.cam2.bits.hyed_r == reset.cam2.bits.hyed_r);
        cam[3].bits.zed = (df.cam2.bits.hzed_r == reset.cam2.bits.hzed_r);
        cam[3].bits.fz = (df.cam2.bits.hfz_r == reset.cam2.bits.hfz_r);

        memcpy(cam_state_out, cam, 4);
    }
    else
    {
        /* 上位机格式转换为下位机格式 */
        memcpy(cam, cam_state_in, 4);
        /* cam1 */
        df.cam1.bits.hzjz_l = reset.cam1.bits.hzjz_l ? cam[1].bits.zjz : !cam[1].bits.zjz;
        df.cam1.bits.hdm_l = reset.cam1.bits.hdm_l ? cam[1].bits.dm : !cam[1].bits.dm;
        df.cam1.bits.hyjz_l = reset.cam1.bits.hyjz_l ? cam[1].bits.yjz : !cam[1].bits.yjz;
        df.cam1.bits.hzed_l = reset.cam1.bits.hzed_l ? cam[1].bits.zed : !cam[1].bits.zed;
        df.cam1.bits.hfz_l = reset.cam1.bits.hfz_l ? cam[1].bits.fz : !cam[1].bits.fz;
        df.cam1.bits.hyed_l = reset.cam1.bits.hyed_l ? cam[1].bits.yed : !cam[1].bits.yed;
        df.cam1.bits.qfz_l = reset.cam1.bits.qfz_l ? cam[0].bits.fz : !cam[0].bits.fz;
        df.cam1.bits.qzed_l = reset.cam1.bits.qzed_l ? cam[0].bits.zed : !cam[0].bits.zed;
        /* cam2 */
        df.cam2.bits.hzjz_r = reset.cam2.bits.hzjz_r ? cam[3].bits.zjz : !cam[3].bits.zjz;
        df.cam2.bits.hdm_r = reset.cam2.bits.hdm_r ? cam[3].bits.dm : !cam[3].bits.dm;
        df.cam2.bits.hyjz_r = reset.cam2.bits.hyjz_r ? cam[3].bits.yjz : !cam[3].bits.yjz;
        df.cam2.bits.hzed_r = reset.cam2.bits.hzed_r ? cam[3].bits.zed : !cam[3].bits.zed;
        df.cam2.bits.hfz_r = reset.cam2.bits.hfz_r ? cam[3].bits.fz : !cam[3].bits.fz;
        df.cam2.bits.hyed_r = reset.cam2.bits.hyed_r ? cam[3].bits.yed : !cam[3].bits.yed;
        df.cam2.bits.qfz_r = reset.cam2.bits.qfz_r ? cam[2].bits.fz : !cam[2].bits.fz;
        df.cam2.bits.qzed_r = reset.cam2.bits.qzed_r ? cam[2].bits.zed : !cam[2].bits.zed;

        /* cam3 */
        df.cam3.bits.qyed_l = reset.cam3.bits.qyed_l ? cam[0].bits.yed : !cam[0].bits.yed;
        df.cam3.bits.qzjz_l = reset.cam3.bits.qzjz_l ? cam[0].bits.zjz : !cam[0].bits.zjz;
        df.cam3.bits.qdm_l = reset.cam3.bits.qdm_l ? cam[0].bits.dm : !cam[0].bits.dm;
        df.cam3.bits.qyjz_l = reset.cam3.bits.qyjz_l ? cam[0].bits.yjz : !cam[0].bits.yjz;
        df.cam3.bits.qyed_r = reset.cam3.bits.qyed_r ? cam[2].bits.yed : !cam[2].bits.yed;
        df.cam3.bits.qzjz_r = reset.cam3.bits.qzjz_r ? cam[2].bits.zjz : !cam[2].bits.zjz;
        df.cam3.bits.qdm_r = reset.cam3.bits.qdm_r ? cam[2].bits.dm : !cam[2].bits.dm;
        df.cam3.bits.qyjz_r = reset.cam3.bits.qyjz_r ? cam[2].bits.yjz : !cam[2].bits.yjz;

        memcpy(cam_state_out, &df, 3);
    }
}
#else
void cam_convert_state(CAM *cam_unsed, uchar *cam_state_in, uchar *cam_state_out,
    int dir, BOOL reset_cmd)
{
    assert(cam_state_in != NULL);
    assert(cam_state_out != NULL);

    CAM_DOWN_FMT_SS df[2];
    CAM_DOWN_FMT_SS reset[2];
    CAM_FMT cam[2] = { { 0 } };

    memset(&df, 0, sizeof(df));
    memset(reset, 0xFF, sizeof(reset));

    if (!reset_cmd)
    {
        reset[0].zjz = 0;
        reset[0].yjz = 0;

        reset[1].zjz = 0;
        reset[1].yjz = 0;
    }

    if (dir == DOWN2UP)
    {
        int i = 0;
        /* 下位机格式转换为上位机格式 */
        memcpy(df, cam_state_in, 2);

        for (i = 0; i < 2; i++)
        {
            cam[i].bits.zjz = (df[i].zjz == reset[i].zjz);
            cam[i].bits.dm = (df[i].dm == reset[i].dm);
            cam[i].bits.yjz = (df[i].yjz == reset[i].yjz);
            cam[i].bits.yed = (df[i].yed == reset[i].yed);
            cam[i].bits.zed = (df[i].zed == reset[i].zed);
            cam[i].bits.fz = (df[i].fz == reset[i].fz);
        }

        memcpy(cam_state_out, cam, 2);
    }
    else
    {
        int i = 0;
        /* 上位机格式转换为下位机格式 */
        memcpy(cam, cam_state_in, 2);

        for (i = 0; i < 2; i++)
        {
            df[i].zjz = reset[i].zjz ? cam[i].bits.zjz : !cam[i].bits.zjz;
            df[i].dm = reset[i].dm ? cam[i].bits.dm : !cam[i].bits.dm;
            df[i].yjz = reset[i].yjz ? cam[i].bits.yjz : !cam[i].bits.yjz;
            df[i].zed = reset[i].zed ? cam[i].bits.zed : !cam[i].bits.zed;
            df[i].fz = reset[i].fz ? cam[i].bits.fz : !cam[i].bits.fz;
            df[i].yed = reset[i].yed ? cam[i].bits.yed : !cam[i].bits.yed;
        }

        memcpy(cam_state_out, df, 2);
    }
}
#endif
/*
 * @param cam: 纱嘴对象
 * @param state: 从下位机读取到的纱嘴状态
 * @param size: state数组大小
 */
void cam_set_state(CAM *cam, uchar *state, int size)
{
    assert(cam != NULL);
    assert(state != NULL);

    cam_convert_state(cam, &state[0], &cam->state[0], DOWN2UP, FALSE);
    if (size > 4)
    {
        cam_convert_state(cam, &state[4], &cam->state[4], DOWN2UP, FALSE);
    }

    memcpy(cam->state_bk, cam->state, 8);
}

/*
 * @param cam: 三角对象
 * @param state[out]:获取到的三角状态
 *  bit0-5一次为左接针，吊目，右接针，左二度，翻针，右二度
 * @param size: state数组大小
 */
void cam_get_state(CAM *cam, uchar *state, int size)
{
    assert(cam != NULL);
    assert(state != NULL);

    memcpy(state, cam->state, size);
}

void cam_set_group_state(CAM *cam, uchar state, int group)
{
    assert(cam != NULL);

    cam->group_state[group] = state;
}

uchar cam_get_group_state(CAM *cam, int group)
{
    assert(cam != NULL);

    return cam->group_state[group];
}

void cam_stop_cycle(CAM *cam)
{
    assert(cam != NULL);
    timer_stop(&cam->timer);
    ccycle_stop(&cam->reset_cycle);
    ccycle_stop(&cam->cycle);
}

/*
 * @note: 判断是否遇到错误
 */
int cam_encount_error(CAM *cam, FEEDBACK *fb, CCYCLE *cycle)
{
    if (fb != NULL)
    {
        if (fb->error.cam)
        {
            return CRGERROR_CAM;
        }
    }
    return 0;
}

BOOL cam_reset_complete(CAM *cam)
{
    assert(cam != NULL);

    return (ccycle_get_state(&cam->reset_cycle) == CYCLE_STOP);
}

BOOL cam_restore_complete(CAM *cam)
{
    return cam_reset_complete(cam);
}

void cam_start_timer(CAM *cam, TIMEOUT_FUNC pfunc, BOOL now)
{
    assert(cam != NULL);
    if (now)
    {
        timer_start(&cam->timer, CAM_CYCLE_TIME, CAM_CYCLE_TIME, pfunc);
    }
    else
    {
        timer_start(&cam->timer, 0, CAM_CYCLE_TIME, pfunc);
    }
}

CCYCLE* cam_get_cycle(CAM *cam)
{
    assert(cam != NULL);
    return &cam->cycle;
}

BOOL cam_need_restore(CAM *cam)
{
    assert(cam != NULL);
    return memcmp(cam->state, cam->state_bk, sizeof (cam->state));
}


void cam_set_pos(CAM *cam, short *pos, int num)
{
}


void cam_set_restore(CAM *cam, BOOL restore)
{
}
